#include <ogc/pad.h>
#include <stdio.h>
#include <unistd.h>
#include <wiiuse/wpad.h>

#include "controller.h"
#include "dopios.h"
#include "tools.h"

#define MAX_WIIMOTES    4


u32 convertGCToWii(u16 pressed) {
    if (pressed & PAD_BUTTON_A) return WPAD_BUTTON_A;
    if (pressed & PAD_BUTTON_B) return WPAD_BUTTON_B;
    if (pressed & PAD_BUTTON_LEFT) return WPAD_BUTTON_LEFT;
    if (pressed & PAD_BUTTON_RIGHT) return WPAD_BUTTON_RIGHT;
    if (pressed & PAD_BUTTON_UP) return WPAD_BUTTON_UP;
    if (pressed & PAD_BUTTON_DOWN) return WPAD_BUTTON_DOWN;
    if (pressed & PAD_BUTTON_START) return WPAD_BUTTON_HOME;
    if (pressed & PAD_TRIGGER_L) return WPAD_BUTTON_MINUS;
    if (pressed & PAD_TRIGGER_R) return WPAD_BUTTON_PLUS;
    if (pressed & PAD_BUTTON_Y) return WPAD_BUTTON_1;
    if (pressed & PAD_BUTTON_X) return WPAD_BUTTON_2;
    return 0;
}

u32 convertClassicToWii(u32 pressed) {
    if (pressed & WPAD_CLASSIC_BUTTON_A) return WPAD_BUTTON_A;
    if (pressed & WPAD_CLASSIC_BUTTON_B) return WPAD_BUTTON_B;
    if (pressed & WPAD_CLASSIC_BUTTON_LEFT) return WPAD_BUTTON_LEFT;
    if (pressed & WPAD_CLASSIC_BUTTON_RIGHT) return WPAD_BUTTON_RIGHT;
    if (pressed & WPAD_CLASSIC_BUTTON_UP) return WPAD_BUTTON_UP;
    if (pressed & WPAD_CLASSIC_BUTTON_DOWN) return WPAD_BUTTON_DOWN;
    if (pressed & WPAD_CLASSIC_BUTTON_HOME) return WPAD_BUTTON_HOME;
    if (pressed & WPAD_CLASSIC_BUTTON_MINUS) return WPAD_BUTTON_MINUS;
    if (pressed & WPAD_CLASSIC_BUTTON_PLUS) return WPAD_BUTTON_PLUS;
    if (pressed & WPAD_CLASSIC_BUTTON_FULL_L) return WPAD_BUTTON_1;
    if (pressed & WPAD_CLASSIC_BUTTON_FULL_R) return WPAD_BUTTON_2;
    return pressed;
}

int ScanPads(u32 *button) {
    *button = 0;
    u32 pressed, held;
    u16 pressedGC;

    pressed = Wpad_GetButtons();
    held = Wpad_GetButtonsHeld();
    held = convertClassicToWii(held);
    if (!(held & WPAD_BUTTON_UP) && !(held & WPAD_BUTTON_DOWN) && !(held
            & WPAD_BUTTON_LEFT) && !(held & WPAD_BUTTON_RIGHT)) {
        held = 0;
    }
    pressed |= held;
    pressedGC = Pad_GetButtons();

    if (pressed || pressedGC) {
        pressed |= convertGCToWii(pressedGC);
        *button = convertClassicToWii(pressed);
    }

    return *button;
}

void WaitAnyKey() {
    u32 button = 0;
    while (!button && !ExitMainThread) {
        button = WaitButtons();
    }
}

u32 WaitKey(u32 button) {
    u32 pressed = 0;
    
    while (!(pressed & button)) {
        if (ExitMainThread) return 0;
        VIDEO_WaitVSync();
        ScanPads(&pressed);
        if (pressed & WPAD_BUTTON_HOME) ReturnToLoader();
    }

    return pressed;
}

u32 Wpad_GetButtons(void) {
    u32 buttons = 0, cnt;

    /* Scan pads */
    WPAD_ScanPads();

    /* Get pressed buttons */
    for (cnt = 0; cnt < MAX_WIIMOTES; cnt++) {
        WPAD_Flush(cnt);
        buttons |= WPAD_ButtonsDown(cnt);
    }

    return buttons;
}

u32 Wpad_GetButtonsHeld(void) {
    u32 buttons = 0, cnt;

    /* Scan pads */
    WPAD_ScanPads();

    /* Get pressed buttons */
    for (cnt = 0; cnt < MAX_WIIMOTES; cnt++) {
        WPAD_Flush(cnt);
        buttons |= WPAD_ButtonsHeld(cnt);
    }

    return buttons;
}

u32 Pad_GetButtons(void) {
    u32 buttons = 0, cnt;

    /* Scan pads */
    PAD_ScanPads();

    /* Get pressed buttons */
    for (cnt = 0; cnt < 4; cnt++) {
        buttons |= PAD_ButtonsDown(cnt);
    }

    return buttons;
}

// Routine to wait for a button from either the Wiimote or a gamecube
// controller. The return value will mimic the WPAD buttons to minimize
// the amount of changes to the original code, that is expecting only
// Wiimote button presses. Note that the "HOME" button on the Wiimote
// is mapped to the "SELECT" button on the Gamecube Ctrl. (wiiNinja 5/15/2009)
u32 WaitButtons(void) {
    u32 buttons = 0;
    u32 buttonsHeld = 0;
    u32 buttonsGC = 0;
	    
    /* Wait for button pressing */
    while (!buttons && !buttonsGC && !buttonsHeld && !ExitMainThread) {
        // GC buttons
        buttonsGC = Pad_GetButtons();
        
        // Wii buttons
        buttons = Wpad_GetButtons();        
        buttonsHeld = Wpad_GetButtonsHeld();       

		if ((buttonsHeld != WPAD_BUTTON_PLUS) && (buttonsHeld != WPAD_BUTTON_MINUS))			 
		{
            buttonsHeld = 0;			
        }
		
        VIDEO_WaitVSync();
    }

    if (buttonsHeld) {
        usleep(100000);
    }

    buttons |= buttonsHeld;
    buttons |= convertGCToWii(buttonsGC);
    buttons = convertClassicToWii(buttons);
    return buttons;
} // WaitButtons
